#include "queue.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// #define LOG_EN

#ifdef LOG_EN
#include "lw_log.h"
#else
#define log_info(...)
#endif

Queue_t OutUartFifo;
Queue_t InUartFifo;

static _data queue_pop(pQueue_t Q);
static int queue_empty(pQueue_t Q);
static int queue_full(pQueue_t Q);
static int queue_length(pQueue_t Q);
static int queue_clear(pQueue_t Q);
static int queue_push(pQueue_t Q, _data value);

//入队
static int queue_push(pQueue_t Q, _data value)
{
	if(Q == NULL)
	{
		// printf("Q is NULL\n");
		return -1;
	}

	if((Q->rear + 1) % BUFF_SIZE == Q->front)	//判断队列是否满
	{
		// printf("queue is full\n");
		return -1;
	}
	Q->data[Q->rear] = value;
	Q->rear = (Q->rear + 1) % BUFF_SIZE; //代替了上面注释语句

	return 0;

}

//出队
static _data queue_pop(pQueue_t Q)
{
	int ret;
	if(Q == NULL)
	{
		// printf("Q is NULL\n");
		ret = 0;
		log_info("pop1");
	}

	if(Q->front == Q->rear)
	{
		// printf("Q is empty\n");
		ret = 0;
		log_info("pop2");
	}

	ret = Q->data[Q->front];
	Q->front = (Q->front + 1) % BUFF_SIZE;

	log_info("pop ret %d", ret);
	return ret;
}

//判读队列是否空
// 1--空  0--非空
static int queue_empty(pQueue_t Q)
{
	if(Q == NULL)
	{
		// printf("Q is NULL\n");
		return -1;
	}

	return Q->front == Q->rear ? 1 : 0;
}

//判读队列是否满
static int queue_full(pQueue_t Q)
{
	if(Q == NULL)
	{
		// printf("Q is NULL\n");
		return -1;
	}

	return (Q->rear + 1) % BUFF_SIZE == Q->front ? 1 : 0;
}

//获取队列元素个数
static int queue_length(pQueue_t Q)
{
	if(Q == NULL)
	{
		// printf("Q is NULL\n");
		return -1;
	}

	return ((Q->rear + BUFF_SIZE - Q->front) % BUFF_SIZE); 
}

//清空队列
static int queue_clear(pQueue_t Q)
{
	if(Q == NULL)
	{
		// printf("Q is NULL\n");
		return -1;
	}

	Q->front = Q->rear = 0;
	
	return 0;
}

/**
 * @brief 初始化队列
 * 
 * @param Q 
 * @return int 
 */
int queue_init(pQueue_t Q)
{
	if (Q != NULL)
	{
		memset((void *)Q, 0u, sizeof(Queue_t));
		return 0;
	}
	else 
	{
		return -1;
	}
}

/**
 * @brief 将数据写入队列
 * 
 * @param q 		队列句柄
 * @param buff 		数据指针
 * @param len 		数据长度
 * @return uint8 
 */
uint8 FifoWriteBytes(pQueue_t q, uint8 *buff, uint16 len)
{	
	uint8 ret = 0u;
	
	log_info("buff %s len %d", buff, len);

	// 需要关闭全局中断
	__disable_irq();
	for (uint16 i = 0; i < len; i++)
	{
		ret = queue_push(q, *buff++);
		// log_info("push ret %d", ret);
		if (ret != 0)
		{
			break;
		}
	}
	// 开启全局中断
	__enable_irq();

	return ret;
}

/**
 * @brief 从队列中读出数据
 * 
 * @param q 		队列句柄
 * @param buff 		数据指针
 * @param len 		数据长度
 * @return uint16 
 */
uint16 FifoReadBytes(pQueue_t q, uint8 *buff, uint16 len)
{	
	uint16 len_r = 0;
	
	log_info("fifo read func %#x len %d", buff, len);
	// 需要关闭全局中断
	__disable_irq();
	if ((buff != NULL) || (q != NULL))
	{
		for (uint16 i = 0; i < len; i++)
		{
			if (queue_empty(q) != 1u)	// == 1 非空
			{
				*buff++ = (uint8)queue_pop(q);
				len_r++;
				log_info("pop data %c", *(buff - 1u));
			}
			else
			{
				log_info("fifo empty!");
				break;
			}
		}
	}
	// 开启全局中断
	__enable_irq();
	
	return len_r;
}

/**
 * @brief 	获取队列中数据量
 * 
 * @param q 
 * @return uint16 
 */
uint16 FifoGetused(pQueue_t q)
{
	if (q == NULL)
	{
		return 0xffff;
	}

	return queue_length(q);
}